/*
 *  WaveTableFactory.cpp
 *  SoundController0002
 *
 *  Created by jiro on 10/11/22.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#include "WaveTableFactory.h"

namespace sc
{
	std::vector< const WaveTable* > WaveTableFactory::waveTables;

	const WaveTable& WaveTableFactory::Create( WaveTable::Type type, double frequency, double adjuster, double phaseShift )
	{
		WaveTable* table;
		SineWaveTable sineWaveTable = SineWaveTable( frequency, phaseShift, adjuster );
		ConstantWaveTable constantWaveTable = ConstantWaveTable( frequency );
		switch ( type ) {
		case WaveTable::Type_Sine:
			table = & sineWaveTable;
			break;
		case WaveTable::Type_Constant:
			table = & constantWaveTable;
			break;
		case WaveTable::Type_Array:
			throw Exception( "invalid type" );
			break;
		default:
			return *NullWaveTable::GetInstance();
		}

		int count = waveTables.size();
		for ( int i = 0; i < count; i++ )
		{
			if ( *(waveTables[ i ]) == *table )
			{
				return * waveTables[ i ];
			}
		}

		switch ( type ) {
		case WaveTable::Type_Sine:
			table = new SineWaveTable( frequency, phaseShift, adjuster );
			break;
		case WaveTable::Type_Constant:
			table = new ConstantWaveTable( frequency );
			break;
		}
		waveTables.push_back( table );
		return * table;
	}

	const WaveTable& WaveTableFactory::CreateSin( double frequency, double phaseShift, double adjuster )
	{
		const WaveTable* tablePtr = Get( SineWaveTable( frequency, phaseShift, adjuster ) );
		if ( tablePtr != NULL  )
		{
			return * tablePtr;
		}
		tablePtr = new SineWaveTable( frequency, phaseShift, adjuster );
		waveTables.push_back( tablePtr );
		return * tablePtr;
	}

	const WaveTable& WaveTableFactory::Create( const WaveTable& waveTable, double adjuster )
	{
		const WaveTable* tablePtr;
		switch ( waveTable.GetType() ) {
		case WaveTable::Type_Sine:
			{
				SineWaveTable table( waveTable.GetFrequency(), 0.0, adjuster );
				tablePtr = Get( table );
				if ( tablePtr != NULL )
				{
					return * tablePtr;
				}
				tablePtr = new SineWaveTable( waveTable.GetFrequency(), 0.0, adjuster );
			}
			break;
		case WaveTable::Type_Constant:
			{
				ConstantWaveTable table( waveTable.GetFrequency() );
				tablePtr = Get( table );
				if ( tablePtr != NULL  )
				{
					return * tablePtr;
				}
				tablePtr = new ConstantWaveTable( waveTable.GetFrequency() );
			}
			break;
		case WaveTable::Type_Array:
			{
				const WaveTableWithArray& waveTableWithArray = 
					dynamic_cast< const WaveTableWithArray& >( waveTable );
				WaveTableWithArray table( waveTableWithArray.GetArray(), adjuster );
				tablePtr = Get( table );
				if ( tablePtr != NULL  )
				{
					return * tablePtr;
				}
				tablePtr = new WaveTableWithArray( waveTableWithArray.GetArray(), adjuster );
			}
			break;
		case WaveTable::Type_Function:
			{
				const WaveTableWithWaveFunction& ref = dynamic_cast< const WaveTableWithWaveFunction& >( waveTable );
				WaveTableWithWaveFunction table( ref.GetWaveFunction(), adjuster );
				tablePtr = Get( table );
				if ( tablePtr != NULL  ) {
					return * tablePtr;
				}
				tablePtr = new WaveTableWithWaveFunction( table.GetWaveFunction(), adjuster );
			}
			break;
		default:
			throw Exception( "unknown type" );
		}

		waveTables.push_back( tablePtr );
		return * tablePtr;
	}

	const WaveTable& WaveTableFactory::Create( const WaveFunction& function, double adjuster )
	{
		WaveTableWithWaveFunction table( function, adjuster );
		const WaveTable* tablePtr = Get( table );
		if ( tablePtr != NULL ) {
			return *tablePtr;
		}
		tablePtr = new WaveTableWithWaveFunction( function, adjuster );
		waveTables.push_back( tablePtr );
		return *tablePtr;
	}

	const WaveTable* WaveTableFactory::Get( const WaveTable& table )
	{
		size_t count = waveTables.size();
		for ( int i = 0; i < count; i++ ) {
			if ( *waveTables[ i ] == table ) {
				return waveTables[ i ];
			}
		}
		return NULL;
	}

	bool WaveTableFactory::IsExist( const WaveTable& table ) 
	{
		if ( Get( table ) == NULL ) {
			return false;
		}
		return true;
	} 

}
